package com.changgou.search.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.changgou.goods.Feign.skuFeign;
import com.changgou.goods.pojo.Sku;
import com.changgou.search.dao.SkuMapper;
import com.changgou.search.pojo.SkuInfo;
import com.changgou.search.service.SkuService;
import com.changgou.util.Result;
import com.sun.org.apache.bcel.internal.generic.NEW;
import net.sf.jsqlparser.statement.select.First;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @ClassName: DemoServiceImpl
 * @Author: ZWJ
 * @Date: 2020-08-30 20:10
 * @Synopsis: Null
 **/
@Service
public class DemoServiceImpl  {
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private skuFeign skuFeign;
    @Autowired
    private ElasticsearchTemplate elTemplate;

    /***
     * 搜索
     * @param searchMap
     * @return
     */
    public Map search01(Map<String, String> searchMap) {
        Map<String, Object> objectMap = new HashMap<>();
        //创建查询器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //组合查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (searchMap != null) {
            //关键字查询
            if (!StringUtils.isEmpty(searchMap.get("keywords"))) {
                String keywords = searchMap.get("keywords");
                // builder.withQuery(QueryBuilders.matchQuery("name",keyword));
                //设置查询
                boolQueryBuilder.must(QueryBuilders.matchQuery("name", keywords));
            }
            //品牌查询
            if (!StringUtils.isEmpty(searchMap.get("brand"))) {
                //品牌进行组合查询
                String brand = searchMap.get("brand");
                //设置查询
                boolQueryBuilder.must(QueryBuilders.termQuery("brandName", brand));
            }
            //分类查询
            if (!StringUtils.isEmpty(searchMap.get("category"))) {
                String category = searchMap.get("category");
                //设置查询
                boolQueryBuilder.must(QueryBuilders.termQuery("categoryName", category));
            }
            //规格查询
            for (Map.Entry<String, String> stringEntry : searchMap.entrySet()) {
                //查看规格是否有查询
                String key = stringEntry.getKey();
                if (key.startsWith("spec_")) {
                    //有规格查询
                    //截取规格名字 spec_...=???
                    String substring = key.substring(5);
                    //获取规格的值
                    String value = stringEntry.getValue();
                    //设置查询
                    boolQueryBuilder.must(QueryBuilders.termQuery("specMap." + substring + ".keyword", value));
                }
            }
            if (!StringUtils.isEmpty(searchMap.get("price"))){

            }
        }

        //排序
        //排序规则
        String sortRule = searchMap.get("sortRule");
        if (sortRule==null){
            sortRule="ASC";
        }
        //排序的域
        String sortField = searchMap.get("sortField");
        if (sortField==null){sortField="price";}
        //设置排序查询
        builder.withSort(SortBuilders.fieldSort(sortField).order(SortOrder.valueOf(sortRule)));

        //分页查询
        String pageNum = searchMap.get("pageNum");
        if (pageNum==null){
            pageNum="1";
        }
        try {
            Integer integer = Integer.valueOf(pageNum);
            if (integer<=0){pageNum="1";}
        } catch (NumberFormatException e) {
            pageNum="1";
        }
        String pageSize = searchMap.get("pageSize");
        pageSize="3";
        PageRequest pageRequest = PageRequest.of(Integer.valueOf(pageNum)-1, Integer.valueOf(pageSize));
        builder.withPageable(pageRequest);
        //将组合查询放入查询器
        builder.withQuery(boolQueryBuilder);

        //不进行品牌的组合查询时
        if (StringUtils.isEmpty(searchMap.get("brand"))) {
            List<String> brandList = new ArrayList<>();
            String brand = searchMap.get("brand");
            //设置聚合查询：设置别名，以及查询的域
            builder.addAggregation(AggregationBuilders.terms("brand").field("brandName").size(1000));
            //执行查询
            AggregatedPage<SkuInfo> skuInfos01 = elTemplate.queryForPage(builder.build(), SkuInfo.class);
            //获取数据
            Aggregations aggregations = skuInfos01.getAggregations();
            StringTerms brand1 = aggregations.get("brand");
            for (StringTerms.Bucket bucket : brand1.getBuckets()) {
                String keyAsString = bucket.getKeyAsString();
                brandList.add(keyAsString);
            }
            objectMap.put("brandList", brandList);
        }
        //不进行分类的组合查询时
        if (StringUtils.isEmpty(searchMap.get("category"))) {
            List<String> categoryList = new ArrayList<>();
            String category = searchMap.get("category");
            //设置聚合查询
            builder.addAggregation(AggregationBuilders.terms("category").field("categoryName").size(10000));
            //执行查询
            AggregatedPage<SkuInfo> skuInfos02 = elTemplate.queryForPage(builder.build(), SkuInfo.class);
            //获取结果集
            Aggregations aggregations = skuInfos02.getAggregations();
            StringTerms stringTerms = aggregations.get("category");
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                //取出数据
                String keyAsString = bucket.getKeyAsString();
                categoryList.add(keyAsString);
            }
            objectMap.put("categoryList", categoryList);
        }
        //规格查询
        if (1>0){
            //存放数据
            Map<String, Set<String>> setMap=new HashMap<>();
            //设置聚合查询
            builder.addAggregation(AggregationBuilders.terms("spec").field("spec.keyword").size(10000));
            //执行查询
            AggregatedPage<SkuInfo> skuInfos03 = elTemplate.queryForPage(builder.build(), SkuInfo.class);
            //获取数据
            Aggregations aggregations = skuInfos03.getAggregations();
            //取出别名的数据进行遍历
            StringTerms specs = aggregations.get("spec");
            for (StringTerms.Bucket bucket : specs.getBuckets()) {
                //取出每条数据
                String keyAsString = bucket.getKeyAsString();
                //将json数据转成map数据
                Map<String,String> map = JSONObject.parseObject(keyAsString, Map.class);
                for (Map.Entry<String, String> stringEntry : map.entrySet()) {
                    //获取到规格名字
                    String key = stringEntry.getKey();
                    //获取到规格的值
                    String value = stringEntry.getValue();
                    //获取同一规格名字的值的集合
                    Set<String> stringSet = setMap.get(key);
                    if (stringSet==null){
                        //没有改规格则创建一个
                        stringSet=new HashSet<>();
                    }
                    stringSet.add(value);
                    //将数据存入map
                    setMap.put(key,stringSet);
                }
            }
            objectMap.put("specList",setMap);
        }

        //高亮查询
        //设置高亮的域
        HighlightBuilder.Field field = new HighlightBuilder.Field("name");
        //设置前缀
        field.preTags("<font style='color:red'");
        //设置后缀
        field.postTags("</font>");
        //设置高亮字符串
        field.fragmentOffset(100);
        //高亮设置放置在查询器
        builder.withHighlightFields(field);
        AggregatedPage<SkuInfo> skuInfos = elTemplate.queryForPage(builder.build(), SkuInfo.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                List<T> skuInfoList = new ArrayList<>();
                //获取结果集
                SearchHits hits = searchResponse.getHits();
                for (SearchHit hit : hits.getHits()) {
                    //获取每条数据
                    String sourceAsString = hit.getSourceAsString();
                    //将每条数据转成javabean
                    SkuInfo skuInfo = JSONObject.parseObject(sourceAsString, SkuInfo.class);
                    //获取指定域的高亮数据
                    HighlightField name = hit.getHighlightFields().get("name");
                    if (name != null) {
                        //获取出高亮的数据
                        Text[] fragments = name.getFragments();
                        String data = "";
                        for (Text fragment : fragments) {
                            data = fragment.toString() + "";
                        }
                        //将SkuInfo数据中的数据替换成高亮数据
                        skuInfo.setName(data);
                    }
                    skuInfoList.add((T) skuInfo);
                }
                return new AggregatedPageImpl<T>(skuInfoList, pageable, hits.getTotalHits(), searchResponse.getAggregations());
            }
        });
        List<SkuInfo> content = skuInfos.getContent();
        objectMap.put("skuList", content);

        return objectMap;
    }

    /***
     * 导入SKU数据
     */

    public void importSku() {
        //远程调用获取数据中的数据
        Result<List<Sku>> byStatus = skuFeign.findByStatus("1");
        //取出sku的结果集
        List<Sku> skus = byStatus.getData();
        //存放skuinfo数据
        List<SkuInfo> skuInfoList = new ArrayList<>();
        //补充数据
        for (Sku sku : skus) {
            //sku与skuinfo两个javabean数据进行转换
            //将sku数据类型转换成json字符串
            String skuString = JSONObject.toJSONString(sku);
            //将json字符串转换成skuinfo对象
            SkuInfo skuInfo = JSONObject.parseObject(skuString, SkuInfo.class);
            //skuinfo中specMap缺少数据需要进行补充
            //取出规格数据
            String spec = skuInfo.getSpec();
            //将规格数据转成json格式数据
            String specString = JSONObject.toJSONString(spec);
            //将json数据转成map格式
            Map<String, Object> map = JSONObject.parseObject(specString, Map.class);
            //将skuinfo中specMap数据补全
            skuInfo.setSpecMap(map);
            skuInfoList.add(skuInfo);
        }
        //将数据存入el中
        skuMapper.saveAll(skuInfoList);
    }


}
